# coding: utf-8
import json
from typing import Any, Type


class AssertUtil:

    def __dir__(self):
        return ['equal', 'is_200', 'is_empty', 'is_false', 'is_in', 'is_instance', 'is_json', 'is_none', 'is_not_in',
                'is_not_instance', 'is_not_json', 'is_not_none', 'is_true', 'not_equal']

    @classmethod
    def equal(cls, actual: Any, expected: Any, message: str = None, **kwargs):
        """
        断言两个值相等。
        :param actual: Actual value.
        :param expected: Expected value.
        :param message: Message to display on failure.
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 期望值: {expected}, 两值不相等'
        assert actual == expected, msg

    @classmethod
    def not_equal(cls, actual: Any, expected: Any, message=None, **kwargs):
        """
        断言两个值不相等。
        :param actual:
        :param expected:
        :param message:
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 期望值: {expected}, 两值相等'
        assert actual != expected, msg

    @classmethod
    def is_true(cls, actual: Any, message=None, **kwargs):
        """
        Assert that a value is True.
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 不是True'

        assert actual is True, msg

    @classmethod
    def is_false(cls, actual: Any, message=None, **kwargs):
        """
        断言某个值为False。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 不是False'
        assert actual is False, msg

    @classmethod
    def is_none(cls, actual: Any, message=None, **kwargs):
        """
        断言某个值为None。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 不是None'
        assert actual is None, msg

    @classmethod
    def is_not_none(cls, actual: Any, message=None, **kwargs):
        """
        断言一个值不是None。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 是 None'
        assert actual is not None, msg

    @classmethod
    def is_in(cls, actual: Any, expected: Any, message=None, **kwargs):
        """
        断言值在容器中。
        :param actual: 实际值。
        :param expected: 期望值。
        :param message: 错误信息。
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 不在容器中: {expected}'
        assert actual in expected, msg

    @classmethod
    def is_not_in(cls, actual: Any, expected: Any, message=None, **kwargs):
        """
        断言值不在容器中。
        :param actual: 实际值。
        :param expected: 期望值。
        :param message: 错误信息。
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 在容器中: {expected}'
        assert actual not in expected, msg

    @classmethod
    def is_instance(cls, actual: Any, expected: Type, message=None, **kwargs):
        """
        断言值是类或类元组的实例。
        :param actual:
        :param expected:
        :param message:
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 不是 {expected} 的实例'
        assert isinstance(actual, expected), msg

    @classmethod
    def is_not_instance(cls, actual: Any, expected, message=None, **kwargs):
        """
        断言一个值不是类的实例或类的元组。
        :param actual:
        :param expected:
        :param message:
        :return:
        """
        if message:
            msg = message % (actual, expected)
        else:
            msg = f'实际值: {actual}, 是 {expected} 的实例'
        assert not isinstance(actual, expected), msg

    @classmethod
    def is_json(cls, actual: Any, message=None, **kwargs):
        """
        断言一个值是一个有效的JSON字符串。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 不是有效的JSON字符串'
        try:
            json.loads(actual)
            assert True, msg
        except ValueError:
            assert False, msg

    @classmethod
    def is_not_json(cls, actual: Any, message=None, **kwargs):
        """
        断言一个值不是一个有效的JSON字符串。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 是有效的JSON字符串'
        try:
            json.loads(actual)
            assert False, msg
        except ValueError:
            assert True, msg

    @classmethod
    def is_empty(cls, actual: Any, message=None, **kwargs):
        """
        断言值为空。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'实际值: {actual}, 不是空'
        assert not actual, msg

    @classmethod
    def is_200(cls, actual: int, message=None, **kwargs):
        """
        断言响应状态码为200。
        :param actual:
        :param message:
        :return:
        """
        if message:
            msg = message % actual
        else:
            msg = f'响应状态码: {actual}, 不是200'
        assert actual == 200, msg
